package com.wtf.dsp.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wtf.dsp.admin.entity.WtfDspDatasource;
import com.wtf.dsp.admin.entity.WtfDspNamespace;
import com.wtf.dsp.admin.enums.CommonErrorEnum;
import com.wtf.dsp.admin.exception.WtfDspException;
import com.wtf.dsp.admin.core.executor.WtfDynamicDataSourceMybatisConfigExecutor;
import com.wtf.dsp.admin.mapper.WtfDspDatasourceMapper;
import com.wtf.dsp.admin.mapper.WtfDspNamespaceMapper;
import com.wtf.dsp.admin.model.dto.*;
import com.wtf.dsp.admin.model.vo.NsListVO;
import com.wtf.dsp.admin.service.NamespaceService;
import com.wtf.dsp.core.constant.NsConstant;
import com.wtf.dsp.core.util.PageUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * ClassName: NamespaceServiceImpl
 * Description:
 * date: 2023/7/7 16:56
 *
 * @author linhuanyou
 * @version 1.0
 */
@Slf4j
@Service
public class NamespaceServiceImpl implements NamespaceService {

    @Resource
    private WtfDspNamespaceMapper wtfDspNamespaceMapper;

    @Resource
    private WtfDspDatasourceMapper wtfDspDatasourceMapper;

    @Resource
    private WtfDynamicDataSourceMybatisConfigExecutor wtfDynamicDataSourceMybatisConfigExecutor;

    @Override
    public PageUtils page(NsPageDTO nsPageDTO) {
        Page<?> page = PageHelper.startPage(nsPageDTO.getPage(), nsPageDTO.getLimit());
        LambdaQueryWrapper<WtfDspNamespace> wtfNameSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.hasLength(nsPageDTO.getNs())){
            wtfNameSpaceLambdaQueryWrapper.like(WtfDspNamespace::getNs,nsPageDTO.getNs());
        }
        wtfNameSpaceLambdaQueryWrapper.orderByAsc(WtfDspNamespace::getId);
        List<NsListVO> nsListVOS = wtfDspNamespaceMapper.selectList(wtfNameSpaceLambdaQueryWrapper).stream().map(e->{
            NsListVO nsListVO = new NsListVO();
            nsListVO.setId(e.getId());
            nsListVO.setNs(e.getNs());
            nsListVO.setName(e.getName());
            nsListVO.setDescription(e.getDescription());
            LambdaQueryWrapper<WtfDspDatasource> wtfDataSourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
            wtfDataSourceLambdaQueryWrapper.eq(WtfDspDatasource::getNs,nsListVO.getNs());
            nsListVO.setDss(wtfDspDatasourceMapper.selectCount(wtfDataSourceLambdaQueryWrapper));
            return nsListVO;
        }).collect(Collectors.toList());
        return new PageUtils(nsListVOS, (int) page.getTotal(), nsPageDTO.getLimit(),nsPageDTO.getPage());
    }

    @Override
    public NsListVO info(String ns) {
        LambdaQueryWrapper<WtfDspNamespace> wtfDspNamespaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDspNamespaceLambdaQueryWrapper.eq(WtfDspNamespace::getNs,ns);
        WtfDspNamespace wtfDspNamespace = wtfDspNamespaceMapper.selectOne(wtfDspNamespaceLambdaQueryWrapper);
        if(wtfDspNamespace == null){
            return null;
        }
        NsListVO nsListVO = new NsListVO();
        BeanUtils.copyProperties(wtfDspNamespace,nsListVO);
        return nsListVO;
    }

    @Override
    public List<NsListVO> list(NsListDTO nsListDTO) {
        List<NsListVO> nsListVOS = wtfDspNamespaceMapper.selectList(null).stream().map(e->{
            NsListVO nsListVO = new NsListVO();
            BeanUtils.copyProperties(e,nsListVO);
            return nsListVO;
        }).sorted(Comparator.comparing(NsListVO::getId)).collect(Collectors.toList());
        return nsListVOS;
    }

    @Override
    public int add(NsAddDTO nsAddDTO) {
        LambdaQueryWrapper<WtfDspNamespace> wtfNameSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfNameSpaceLambdaQueryWrapper.eq(WtfDspNamespace::getNs,nsAddDTO.getNs());
        if(wtfDspNamespaceMapper.selectCount(wtfNameSpaceLambdaQueryWrapper) > 0 ){
            throw new WtfDspException(CommonErrorEnum.NAMESPACE_EXIST);
        }
        WtfDspNamespace wtfNameSpace = new WtfDspNamespace();
        wtfNameSpace.setNs(nsAddDTO.getNs());
        wtfNameSpace.setName(nsAddDTO.getName());
        wtfNameSpace.setDescription(nsAddDTO.getDescription());
        int add = wtfDspNamespaceMapper.insert(wtfNameSpace);
        return add;
    }

    @Override
    public int remove(NsDelDTO nsDelDTO) {
        boolean defaultNs = nsDelDTO.getNss().stream().filter(e->{return NsConstant.DEFAULT_NS.equals(e);}).findFirst().isPresent();
        if(defaultNs){
            throw new WtfDspException(CommonErrorEnum.DEFAULT_NAMESPACE_DEL_ERROR);
        }
        LambdaQueryWrapper<WtfDspDatasource> wtfDataSourceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfDataSourceLambdaQueryWrapper.in(WtfDspDatasource::getNs, nsDelDTO.getNss());
        if(wtfDspDatasourceMapper.selectCount(wtfDataSourceLambdaQueryWrapper) > 0 ){
            throw new WtfDspException(CommonErrorEnum.NAMESPACE_DS_ERROR);
        }
        LambdaQueryWrapper<WtfDspNamespace> wtfNameSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfNameSpaceLambdaQueryWrapper.in(WtfDspNamespace::getNs, nsDelDTO.getNss());
        int delete = wtfDspNamespaceMapper.delete(wtfNameSpaceLambdaQueryWrapper);
        return delete;
    }

    @Override
    public int update(NsUpdateDTO nsUpdateDTO) {
        if(NsConstant.DEFAULT_NS.equals(nsUpdateDTO.getNs())){
            throw new WtfDspException(CommonErrorEnum.DEFAULT_NAMESPACE_ERROR);
        }
        LambdaQueryWrapper<WtfDspNamespace> wtfNameSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        wtfNameSpaceLambdaQueryWrapper.eq(WtfDspNamespace::getNs,nsUpdateDTO.getNs());
        WtfDspNamespace wtfNameSpace = new WtfDspNamespace();
        wtfNameSpace.setName(nsUpdateDTO.getName());
        wtfNameSpace.setDescription(nsUpdateDTO.getDescription());
        return wtfDspNamespaceMapper.update(wtfNameSpace,wtfNameSpaceLambdaQueryWrapper);
    }

}
